package descentFly {
	import UIFree.ObjectEvent;
	import UIFree.uif_Timer;
	
	import UIUtils.uif_util;
	
	import api_servers.api_myserver;
	
	import descentFly.app.df_events;
	import descentFly.away3D4.net.df_netChip;
	import descentFly.chips.df_chip;
	import descentFly.server.myserver;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.utils.Timer;
	
	import flashx.textLayout.formats.Float;

	public class df_player extends df_optionsObject {
		public static const RANKCOUNT	: int = 19;
		public static const BONUSSTEP	: int = 16;
		public static const LESIONSTEP	: int = 4;
		public static const BOUNDS_DIV	: int = 10;
		
		private var _myChip		: df_chip;
		private var _space		: df_space;
		private var _server		: myserver;
		private var _topStage	: EventDispatcher;
		
		public function df_player(a_options: Object, a_server: myserver, a_topStage: EventDispatcher) {
			super(a_options);
			_server 	= a_server;
			_topStage	= a_topStage;
		}
		
		override protected function setOptions(a_options:Object):void {
			updateParams(a_options);
			super.setOptions(a_options);
		}
		
		protected function updateParams(params: Object): void {
			params.login 	= (params.login == '0')?'':params.login; 
			params.chip 	= parseInt(params.chip);
			params.live 	= parseInt(params.live);
			params.level 	= parseInt(params.level);
			params.rank 	= parseInt(params.rank);
			params.bonus 	= parseInt(params.bonus);
			params.status 	= parseInt(params.status);
			params.victory 	= parseInt(params.victory);
			params.fullVictory 	= parseInt(params.fullVictory);
			params.lesions 		= parseInt(params.lesions);
			params.fullLesions 	= parseInt(params.fullLesions);
			params.balance 		= parseFloat(params.balance);
		}
		
		public function setSpace(a_space: df_space): void {
			if (_space) removeEventsSpace();
			_space = a_space;
			if (_space) listernEventsFromSpace();
		}
		
		protected function removeEventsSpace(): void {
			_space.removeEventListener(df_space.SETMYCHIP, doSetMyChip);
			_space.removeEventListener(df_space.CHANGELEVEL, doChangeLevel);
			
			_topStage.removeEventListener(df_events.KILLER, doNetKiller);
			_topStage.removeEventListener(df_events.CREATEBATTLE, doCreateBattle);
		}
		
		protected function listernEventsFromSpace(): void {
			_space.addEventListener(df_space.SETMYCHIP, doSetMyChip);
			_space.addEventListener(df_space.CHANGELEVEL, doChangeLevel);
			
			_topStage.addEventListener(df_events.KILLER, doNetKiller);
			_topStage.addEventListener(df_events.CREATEBATTLE, doCreateBattle);
		}
		
		override protected function removeEvents():void {
			super.removeEvents();
			removeEventsSpace();
		}
		
		protected function removeMyChipEvents(): void {
			_myChip.removeEventListener(df_chip.LIVECHANGE, doLiveChange);
			_myChip.removeEventListener(df_chip.DESTRUCTION, doDestruction);
			_myChip.removeEventListener(df_chip.IKILLED, doIKilled);
		}
		
		protected function addMyChipEvents(): void {
			_myChip.addEventListener(df_chip.LIVECHANGE, doLiveChange);
			_myChip.addEventListener(df_chip.DESTRUCTION, doDestruction);
			_myChip.addEventListener(df_chip.IKILLED, doIKilled);
		}
		
		protected function doSetMyChip(e: ObjectEvent): void {
			if (_myChip) removeMyChipEvents();
			_myChip = e.object as df_chip;
			if (_myChip) addMyChipEvents();
		}
		
		public function get UID(): uint {
			return options.uid;
		}
		
		public function get rank(): int {
			return options.rank;
		}
		
		public function get live(): int {
			return options.live;
		}
		
		public function get level(): int {
			return options.level;
		}
		
		public function get login(): String {
			return options.login;
		}
		
		public function get source(): int {
			return options.source;
		}
		
		public static function calculateNextRank(a_curRank: int, a_victory: int, a_lesions: int, a_bonus: Number): Number {
			var v_bonus: Number = (a_victory - a_lesions * a_curRank/RANKCOUNT);
			return (a_bonus/BOUNDS_DIV + v_bonus)/BONUSSTEP;
		}
		
		public function get nextStatus(): Number {
			return calculateNextRank(rank, options.victory, options.lesions, options.bonus);
		}
		
		public function getOnlineBattles(retFunc: Function): void {
			_server.oneQuery('getOnlineBattles', UID.toString(), function(data: Object): void {
				retFunc(data.response[0]);
			});
		}
		
		protected function createBattle(name: String, levelID: int, maxUsers: int, monstersIndex: int, options: Object, handle: Function): void {
			_server.oneQuery('createBattle', UID + ';' + name  + ';' + levelID + ';' + 
											maxUsers + ';' + monstersIndex + ';' + (options?JSON.stringify(options):''), function(data: Object): void {
				handle(data.response[0]);
			});
		}
		
		private function doCreateBattle(e: ObjectEvent): void {
			var battleObject: Object = e.object;
			createBattle(battleObject.name, battleObject.id, battleObject.maxUsers, battleObject.monstersIndex, battleObject.options, function(data: Object): void {
				e.target.dispatchEvent(new ObjectEvent(df_events.LOAD_ONLINEBATTLE, uif_util.union(battleObject, data), true));
			});
		}
		
		protected function addQuery(method: String, params: String='', func: Function=null): void {
			_server.addQuery(method, UID + ';' + params);
		}
		
		protected function setProperty(propertyName: String, value: Object): void {
			if (options[propertyName] != value) {
				addQuery('set' + propertyName, value.toString());
				options[propertyName] = value;
			}
		}
		
		protected function doChangeLevel(e: Event): void {
			setProperty('level', _space.levelID);
		}
		
		protected function nextRank(): void {
			options.rank ++;
			options.fullVictory += options.victory; 
			options.fullLesions += options.lesions; 
			options.victory = 0;
			options.lesions = 0;
			options.bonus	= 0;
			dispatchEvent(new Event(df_events.CHANGEPLAYERRANK));
		}
		
		protected function updatePlayerStatus(): void {
			if ((nextStatus >= 1) && (rank < RANKCOUNT)) { 
				nextRank();
			}
			_server.oneQuery('updateStatus', UID + ';' + options.victory + ';' + options.lesions + ';' + 
										options.fullVictory + ';' + options.fullLesions + ';' + options.bonus + ';' + rank);
			dispatchEvent(new Event(df_events.CHANGEPLAYERSTATUS));
		}
		
		protected function doVictory(killUID: uint=0): void {
			options.victory++; 
			updatePlayerStatus();
		}
		
		protected function doNetKiller(e: ObjectEvent): void {
			if (e.object.killer == UID) {
				doVictory(e.object.uid);
			}
		}
		
		protected function doIKilled(e: ObjectEvent): void {
//			doVictory();
			if (e.object.options.bonus) 
					bonus += parseInt(e.object.options.bonus);
		}
		
		public function get bonus(): int {
			return options.bonus;
		}
		
		public function set bonus(a_value: int): void {
			if (options.bonus != a_value) {
				options.bonus = a_value; 
				updatePlayerStatus();
			}
		}
		
		protected function doDestruction(e: ObjectEvent): void {
			if (e.object is df_netChip) { // Защитываем поражения если убил другой игрок
				var netRange: Number = calculateNextRank(rank, options.victory, options.lesions + 1, options.bonus);
				if (netRange > 0) {
					options.lesions++;
					updatePlayerStatus();
				}
			}
		}
		
		protected function doLiveChange(e: Event): void {
			setProperty('live', Math.round(_myChip.live * 100));
		}
		
		public function updateLoginPassword(a_login: String, a_passwordEncrypt: String): void {
			_server.oneQuery('updateLoginPassword', UID + ';' + a_login + ';' + a_passwordEncrypt);
		}
		
		public function loginUser(a_login: String, a_passwordEncrypt: String, retFunc: Function): void {
			_server.oneQuery('loginUser', UID + ';' + a_login + ';' + a_passwordEncrypt, function(data: Object): void {
				doEnterLoginComplete(data.response[0], retFunc);
			});
		}
		
		protected function doEnterLoginComplete(data: Object, retFunc: Function): void {
			if (data && data.uid) {
				setOptions(data);
				retFunc(true)
			} else retFunc(false)
		}
	}
}